package cn.wgx.commons.aop;

import cn.wgx.commons.util.Servlets;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

/**
 * 一个单次请求的缓存
 */
@Aspect
@Component
@Slf4j
public class RequestCache {


    @Pointcut("@annotation(cn.wgx.commons.annotation.RequestCache)")
    public void cutPermission2() {    }

    @Before("cutPermission2()")
    public void preCache(JoinPoint joinPoint) {
        System.out.println("目标方法名为:" + joinPoint.getSignature().getName());
    }

    @Around("cutPermission2()")
    public Object preCache(ProceedingJoinPoint joinPoint) {
        System.out.println("目标方法名为:" + joinPoint.getSignature().getName());
        System.out.println("目标方法所属类的简单类名:" +        joinPoint.getSignature().getDeclaringType().getSimpleName());
        System.out.println("目标方法所属类的类名:" + joinPoint.getSignature().getDeclaringTypeName());
        System.out.println("目标方法声明类型:" + Modifier.toString(joinPoint.getSignature().getModifiers()));
        HttpServletRequest request = Servlets.getRequest();
        if (request == null) {
            try {
                joinPoint.proceed();
            } catch (Throwable throwable) {
                throwable.printStackTrace();
            }
        }
        Object[] args2 = joinPoint.getArgs();
        Signature signature = joinPoint.getSignature();
        String k = signature.getDeclaringType() + signature.getDeclaringType().getSimpleName() + getParamString(args2);
        Object attribute = request.getAttribute(k);
        if (attribute != null) {
            return attribute;
        }
        Object result = null;
        try {
            result = joinPoint.proceed();
            request.setAttribute(k, result);
        } catch (Throwable throwable) {
            log.error("获取RequestCache失败!");
            throwable.printStackTrace();
        }
        return result;
    }

    private String getParamString(Object[] args) {
        StringBuffer s = new StringBuffer();
        for (Object o : args) {
            s.append(o==null?"null":o.toString());
            s.append("|");
        }
        return s.toString();
    }


    private <T extends Annotation> T getMethodAnnotation(ProceedingJoinPoint joinPoint, Class<T> clazz) {
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        Method method = methodSignature.getMethod();
        return method.getAnnotation(clazz);
    }
}
